package folder.main.exp0.linksMapping;

import java.util.LinkedHashMap;

import folder.model.link.Link;
import folder.model.network.Network;
import folder.model.node.Node;
import folder.model.virtual.VirtualNetwork;
import folder.model.virtual.VirtualNode;

public class LinksMappingAlgorithm
{
	public static final String DISTANCE_COST = "distance";
	public static final String BW_COST = "availableBandwidth";
	
	private String name;
	public String getName(){ return name; }
	public void setName( String name ){ this.name = name; }
	
	private String costMetric;
	public String getCostMetric(){ return costMetric; }
	public void setCostMetric( String costMetric ){ this.costMetric = costMetric; }
	
	private boolean isBackupVirtualNetwork;
	public boolean isBackupVirtualNetwork(){ return isBackupVirtualNetwork; }
	public void setBackupVirtualNetwork( boolean isBackupVirtualNetwork ){ this.isBackupVirtualNetwork = isBackupVirtualNetwork; }
	
	public LinksMappingAlgorithm( String name )
	{
		this.setName( name );
	}
	
	public double[][][][] run( VirtualNetwork virtualNetwork, Network network, LinkedHashMap< VirtualNode, Node > nodeMapping )
	{
		double availableBandwiths[][] = this.availableBandwiths( network );
		
		double normalLinkMapping[][][] = this.linkMapping( virtualNetwork, network, nodeMapping, availableBandwiths );
		
		if( normalLinkMapping == null )
			return null;
			
		int virtualLinkNumber = virtualNetwork.getNumberVirtualLinks();
		int nodeNumber = network.getNumberNodes();
		
		double linkMapping[][][][] = new double[ virtualLinkNumber ][ nodeNumber ][ nodeNumber ][ 2 ];

		for( int k = 0; k < virtualLinkNumber; k++ )
			for( int i = 0; i < nodeNumber; i++ )
				for( int j = 0; j < nodeNumber; j++ )
					linkMapping[ k ][ i ][ j ][ 0 ] = normalLinkMapping[ k ][ i ][ j ];
		
		if( this.isBackupVirtualNetwork() )
		{
			for( int k = 0; k < virtualLinkNumber; k++ )
				for( int i = 0; i < nodeNumber; i++ )
					for( int j = 0; j < nodeNumber; j++ )
					{
						if( normalLinkMapping[ k ][ i ][ j ] != 0 )
						{
							availableBandwiths[ i ][ j ] = 0;
							availableBandwiths[ j ][ i ] = 0;
						}
					}
			
			double backupLinkMapping[][][] = this.linkMapping( virtualNetwork, network, nodeMapping, availableBandwiths );
			
			if( backupLinkMapping == null )
				return null;
			
			for( int k = 0; k < virtualLinkNumber; k++ )
				for( int i = 0; i < nodeNumber; i++ )
					for( int j = 0; j < nodeNumber; j++ )
						if( backupLinkMapping[ k ][ i ][ j ] != 0 )
							linkMapping[ k ][ i ][ j ][ 1 ] = backupLinkMapping[ k ][ i ][ j ];
		}
		
		return linkMapping;
	}

	protected double[][][] linkMapping( VirtualNetwork virtualNetwork, Network network, LinkedHashMap< VirtualNode, Node > nodeMapping, double availableBandwiths[][] )
	{
		return null;
	}
	
	public double[][] delays( Network network )
	{
		int nodeNumber = network.getNumberNodes();
		double delays[][] = new double[ nodeNumber ][ nodeNumber ];
		
		for( int i = 0; i < nodeNumber; i++ )
			for( int j = 0; j < nodeNumber; j++ )
				delays[ i ][ j ] = Double.MAX_VALUE; 
		
		for( Link link: network.getLinks() )
		{
			int iNodeA = link.getNodeA().getIdentifier();
			int iNodeB = link.getNodeB().getIdentifier();
			
			delays[ iNodeA ][ iNodeB ] = link.getDelay();
			delays[ iNodeB ][ iNodeA ] = link.getDelay();
		}
		
		return delays;
	}
	
	public double[][] availableBandwiths( Network network )
	{
		int nodeNumber = network.getNumberNodes();
		double availableBandwiths[][] = new double[ nodeNumber ][ nodeNumber ];
		
		for( int i = 0; i < nodeNumber; i++ )
			for( int j = 0; j < nodeNumber; j++ )
				availableBandwiths[ i ][ j ] = 0;
		
		for( Link link: network.getLinks() )
		{
			int iNodeA = link.getNodeA().getIdentifier();
			int iNodeB = link.getNodeB().getIdentifier();
			
			availableBandwiths[ iNodeA ][ iNodeB ] = link.getBandwidthAvailable();
			availableBandwiths[ iNodeB ][ iNodeA ] = link.getBandwidthAvailable();
		}
		
		return availableBandwiths;
	}
	
}
